#include "ProtactorToolView.h"

#include <QVBoxLayout>
#include <QFontDatabase>
#include <QPainter>
#include <QSize>
#include <QByteArray>
#include <QValidator>
#include <QIntValidator>
#include <QDoubleValidator>
#include <QRegularExpressionValidator>
#include <QRegularExpression>
#include <QStringList>
#include <QMessageBox>
#include <QPainterPath>
#include <QDebug>
#include <QString>
#include <QPoint>

#include <QLabel>
#include <QLineEdit>
#include <QPalette>

#include <QTimer>

#include <QRegularExpression>

#include "../IdRootMenu.h"

#include "mcore/tools/EditWidget.h"
#include "mcore/tools/LCToolUtilsMacro.h"


#include "mcore/tools/pick/PickToolByRect.h"

// #include "../../vertex/RemovePointUtils.h"
#include "mcore/tools/vertex/DeleteVertex.h"
#include "mcore/tools/vertex/MoveVertex.h"
#include "mcore/tools/setting/KeToolSettings.h"
#include "mcore/tools/protactor/ProtactorConst.h"

#include "mcore/map/EarthMapConst.h"

#include "GPSValueButtons.h"


#include "../vhc/constview4fun.h"

#include "../tpop/PWindowEditTool.h"

#include "ProDlgHead.h"
#include "AngleGridItem.h"





#include "mcore/tools/EditWidget.h"

#include "mcore/tools/normal/EditTool.h"
#include "mcore/tools/affine/AffinePan.h"
#include "mcore/tools/affine/AffineRotate.h"
#include "mcore/tools/affine/AffineShear.h"
#include "mcore/tools/affine/AffineZoomScale.h"
#include "mcore/tools/line/LineSlideTool.h"
#include "mcore/tools/vertex/VertexAddTool.h"

namespace kepen {
namespace core {


ProtactorToolView::ProtactorToolView(QWidget *parent,int lineOrPolygon,KeSysSetting *config)
    : QVBoxLayout{parent}
    ,m_LineTag(lineOrPolygon)
    ,sysConfig(config)
    ,angleTest(0.0)
{
    setDirection(QBoxLayout::TopToBottom);
    setSpacing(0);
    setContentsMargins(0, 0, 0, 0);
    setAlignment(Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop);



    mapSurface = dynamic_cast<kepen::core::MapObject*>(parent);

    fontLabel.setPointSize(TextSize_Tool);

    int fontId = QFontDatabase::addApplicationFont(config->configView()->fileIconFont);
    QString fontName = QFontDatabase::applicationFontFamilies(fontId).at(0);
    QFont fontIcon = QFont(fontName);
    fontIcon.setPointSize(TextSize_IconFont);

    thirdFontIcon = fontIcon;

    segmentPicked = new SegmentPickedData();



    dlgHead = new ProDlgHead(parent,this,Width_ProtactorToolView);
    //本控件继承自QVBoxLayout
    addWidget(dlgHead);

    m_BodyWidget = NULL;
    m_AngleInput = NULL;
    m_SegInput = NULL;
    m_SegR2Input = NULL;
    m_gpsInput = NULL;

    segmentPicked->mProtaData.setTarget4Pick(Pick_Target_Edge);
    goView4Segment();



}

ProtactorToolView::~ProtactorToolView()
{
    // QLayoutItem *child;
    // QWidget *wg_ch;
    // QSpacerItem *spacerItem;
    // QLayout *_layItem;
    // mapSurface->setActivateTool(NULL);//tool的parent是本类，没有意义，只是添乱
    // this->clearViewVertex();
    // 是有必要的，因为：child->parent === mapSurface,不是本类，本类是QVBoxLayout，不是QWidget
    // while ((child = takeAt(0)) != nullptr) {
    //     wg_ch = child->widget();
    //     if(wg_ch)
    //         delete child->widget();
    //     delete child;
    // }
    if(segmentPicked)
    {
        delete segmentPicked;
        segmentPicked = NULL;
    }



}

int ProtactorToolView::onBtnClicked(int id)
{
    int retFlag = ( IS_Close_Tab(id))?ViewClickFlag_Go:0;
    ProtactorParamData &_paramData = segmentPicked->mProtaData;
    if(IS_Close_Tab(id))
    {
        mapSurface->setActivateTool(NULL);
        mapSurface->repaint();
        QTimer::singleShot(TimeoutClickFree,this,SLOT(timeoutClosedThiz()));

    }else if(Pick_Target_Vertex == id)
    {
        onClickedPickVertex(id);
    }else if(Pick_Target_Edge == id)
    {
        onClickedPickSegment(id);
    }else if(UpdateGPS_ByString == id)
    {
        onUpdateGPSByString();
    }else if(Edit_EraseVertex == id)
    {

        onEditEraseVertex();
    } else if(AngleMode_Hor == id || AngleMode_Intersection == id){
        int v = _paramData.nAngleStruct;
        if(false == (v == id)){
            _paramData.nAngleStruct = id;
        }


        data2view();
        if(mapSurface)
            mapSurface->repaint();

    }else if(Option_EnSnapGraphic ==  id){
        // testAngle();
           kepen::core::EditWidget *ewPtr = mapSurface->getEditWidgetSingleton();
        KeToolSettings *keSetting = ewPtr->getMapToolSettings();
        keSetting->m_EnSnapGraphic = !keSetting->m_EnSnapGraphic;
    }
    else if(AnchorPartSegment_Pre == id || AnchorPartSegment_Post == id){
        int v = _paramData.nSegmentPart;
        if(false == (v == id)){
            _paramData.nSegmentPart = id;
        }

        data2view();
        if(mapSurface)
            mapSurface->repaint();
    }
    return retFlag;
}

int ProtactorToolView::onComboxClicked(int id,int flag,const QPoint &point)
{
    ProtactorParamData &_paramData = segmentPicked->mProtaData;
    if(EditTool_Combox == id){
        clearViewVertex();
        if(Pos_ComboBox_Right == flag)
        {
            QWidget *parent = dlgHead;
            int checkedId = _paramData.nEditTool;
            PWindowEditTool * wPopup  = new PWindowEditTool(parent,checkedId,thirdFontIcon);
            connect(wPopup, SIGNAL(selectedEditToolSignals(QWidget*,int)),
                    this,SLOT(onSelectedEditTool(QWidget*,int)),
                    Qt::ConnectionType(Qt::DirectConnection| Qt::SingleShotConnection));

            wPopup->show();
            wPopup->move(point);

        }else
        {
            int checkedId = _paramData.nEditTool_last;
            onEditToolSelectedImpl(checkedId);
        }
    }
    return ViewClickFlag_RepaintRoot;
}

void ProtactorToolView::repaintToolBar(){

}

void ProtactorToolView::testTimer()
{
    this->onBtnClicked(Pick_Target_Edge);
}

void ProtactorToolView::testAngle()
{
    angleTest += 10;

    double x0 =300,y0=400,len =200,a,a2;
    double x1,y1,x2,y2,x3,y3,xx,yy;
    AffineTransform world2Screen;

    a = qDegreesToRadians(angleTest);
    x1 = x0 + len * std::cos(a);
    y1 = y0 + len * std::sin(a);
    x2 = x0;
    y2 = y0;

    xx = (x1 + x2)/2.0;
    yy = (y1 + y2)/2.0;

    a2 = a +  M_PI_2;
    x3 = xx + len * std::cos(a2);
    y3 = yy + len * std::sin(a2);



    mapSurface->getWorldToScreen(world2Screen);

    world2Screen.invert();
    world2Screen.transformPoint2D(&x1,&y1);
    world2Screen.transformPoint2D(&x2,&y2);
    world2Screen.transformPoint2D(&x3,&y3);

    geos::geom::GeometryFactory::Ptr gf = geos::geom::GeometryFactory::create();
    const std::size_t numPts = 4;
    auto coords = geos::detail::make_unique<geos::geom::CoordinateSequence>(numPts);


    coords->setOrdinate(0,0,x1);
    coords->setOrdinate(0,1,y1);
    coords->setOrdinate(1,0,x2);
    coords->setOrdinate(1,1,y2);
    coords->setOrdinate(2,0,x3);
    coords->setOrdinate(2,1,y3);
    coords->setOrdinate(3,0,x1);
    coords->setOrdinate(3,1,y1);

    std::unique_ptr<LinearRing> ring =  gf->createLinearRing(std::move(coords));

    std::unique_ptr<Polygon> poly =  gf->createPolygon(std::move(ring));

    kepen::core::Graphic *gr =   mapSurface->getEditWidgetSingleton()->getEditGraphicR0();

    gr->setGeom(std::move(poly));

    pickSegmentToolImpl();
}

double ProtactorToolView::getAngleValue()
{
    return angleTest;
}

KeSysSetting *ProtactorToolView::getSysConfig()
{
    return this->sysConfig;
}

void ProtactorToolView::onClickedPickVertex(int id)
{
    ProtactorParamData &param = segmentPicked->mProtaData;
    int val = param.VertexOrEdgeTarget4Pick;
    mapSurface->getEditWidgetSingleton()->getEditPointLayer()->clearData();
    if(val == id)
    {
        // param.resetState();

        // mapSurface->setActivateTool(NULL);

    }else
    {
        mapSurface->setActivateTool(NULL);

        param.setTarget4Pick(id);



        QTimer::singleShot(TimeoutClickFree, this, &ProtactorToolView::goView4Vertex);



    }

}

void ProtactorToolView::onClickedPickSegment(int id)
{
    ProtactorParamData &param = segmentPicked->mProtaData;
    int val = param.VertexOrEdgeTarget4Pick;
    mapSurface->getEditWidgetSingleton()->getEditPointLayer()->clearData();
    if(val == id)
    {
        // param.resetState();

        // mapSurface->setActivateTool(NULL);

    }else
    {
        param.setTarget4Pick(id);
        mapSurface->setActivateTool(NULL);

        // if(m_BodyWidget){
        //     delete m_BodyWidget;
        //     m_BodyWidget=NULL;
        // }
        goView4Segment();

    }
}



void ProtactorToolView::onSelectedEditTool(QWidget *dlg, int id)
{
    onEditToolSelectedImpl(id);

    dlg->deleteLater();

}

void ProtactorToolView::onEditToolSelectedImpl(int id)
{
    if(id != MenuId_None)
    {
        ProtactorParamData &param = segmentPicked->mProtaData;
        int val = param.nEditTool;
        if(id == val)
        {
            param.setEditTool(MenuId_None);
            mapSurface->setActivateTool(NULL);
            mapSurface->repaint();
        }else
        {
            // kepen::core::EditWidget* ew = mapSurface->getEditWidgetSingleton();
            param.setEditTool(id);

            actEditTool(id,true);
            //mapSurface->repaint();
        }

    }
}

void ProtactorToolView::pickSegmentToolImpl()
{
    //&segmentPicked->mProtaData,&segmentPicked->mPickedResult
    ProtractorPickTool *tool = mapSurface->createProtractorTool(m_BodyWidget,segmentPicked);

    // tool->activate(mapSurface);

    connect(tool,SIGNAL(pickedProtractorSignals(kepen::core::ProtractorPickTool*)),
            this,SLOT(onPickProtractorHandler(kepen::core::ProtractorPickTool*)),
            Qt::ConnectionType::DirectConnection);

    mapSurface->repaint();
}

void ProtactorToolView::pickVertexToolImpl()
{
    SnapOption vertexOrEdge =  SnapOption::VERTEX;
    PickToolByRect *tool = new PickToolByRect(m_BodyWidget,vertexOrEdge,isCompatibleClick_Yes,PickToolByRect::BoxByType::BoxByRect);


    connect(tool, SIGNAL(onPickSignals()),
            this,SLOT(onPickVertexHandler()),
            Qt::DirectConnection);
    // not | Qt::SingleShotConnection


    tool->activate(mapSurface);


}

void ProtactorToolView::data2view()
{
    ProtactorParamData &param = segmentPicked->mProtaData;

    if(param.isNull())
    {
        m_AngleInput->clear();
        m_SegInput->clear();
        m_SegR2Input->clear();

    }else
    {
        char ch;
        std::size_t nStrlen;

        double angVal;
        double lengthSegPart;
        double lengthSeg;

        char szBuf[48];
        lengthSeg = param.fValLengthSegment;
        angVal = param.getAngleValue();

        if(AnchorPartSegment_Pre  ==  param.nSegmentPart)
        {
            lengthSegPart = param.fValLengthPre;
        }else lengthSegPart = param.fValLengthSuffix;

        MyFloat2Str(angVal)

            QString strAngale(szBuf);
        m_AngleInput->setText(strAngale);

        MyFloat2Str(lengthSeg)

            QString strLengthSeg(szBuf);
        m_SegR2Input->setText(strLengthSeg);

        MyFloat2Str(lengthSegPart)

            QString strLengthSegPart(szBuf);
        m_SegInput->setText(strLengthSegPart);


    }
}

void ProtactorToolView::isValChanged(ProtactorParamEdit &paramEdited )
{
    quint32 retFlag = 0;
    ProtactorParamData &param = segmentPicked->mProtaData;



    if(false == param.isNull())
    {

        QString angaleStr_new = m_AngleInput->text();
        QString lengthStr_new = m_SegR2Input->text();
        if(false == angaleStr_new.isEmpty() && false == lengthStr_new.isEmpty())
        {
            //Q_GLOBAL_STATIC_WITH_ARGS(QRegularExpression, regExp, {"SEARCHING..."});
            static  QRegularExpression regExp("\\s");
            angaleStr_new.remove(regExp);
            lengthStr_new.remove(regExp);
            // strAngale_new = strAngale_new.simplified();
            // strLength_new = strLength_new.simplified();

            if(false == angaleStr_new.isEmpty() && false == lengthStr_new.isEmpty())
            {
                auto systemLocale = QLocale::system();
                bool b1,b2;
                double fvAngleNew = systemLocale.toDouble(angaleStr_new,&b1);
                double fvLenNew_meter = systemLocale.toDouble(lengthStr_new,&b2);
                if(b1 && b2)
                {
                    bool isAngle,isLength;
                    char ch;
                    std::size_t nStrlen;
                    double angVal;
                    double lengthSeg;
                    char szBuf[48];

                    NormalAngleByAtna2(fvAngleNew)


                        lengthSeg = param.fValLengthSegment;
                    angVal = param.getAngleValue();


                    MyFloat2Str(angVal)

                        QString strAngale(szBuf);
                    MyFloat2Str(lengthSeg)

                        QString strLengthSeg(szBuf);



                    MyFloat2Str(fvAngleNew)

                        QString strAngaleR2(szBuf);
                    MyFloat2Str(fvLenNew_meter)

                        QString strLengthSegR2(szBuf);

                    isAngle = 0 == strAngaleR2.compare(strAngale);
                    isLength = 0 == strLengthSegR2.compare(strLengthSeg);



                    if(false == isAngle)
                        retFlag = Protactor_Attr_Angle;

                    if(false == isLength)
                        retFlag |= Protactor_Attr_Length;

                    paramEdited.fvAngle = fvAngleNew;
                    paramEdited.fvLength_meter = fvLenNew_meter;
                    paramEdited.state = retFlag;
                }
            }
        }




    }

    // return retFlag;
}

void ProtactorToolView::goView4Vertex()
{

    clearViewVertex();
    QString cssInput = QCSS_Input();
    QString css4Body = QString::asprintf("#%s%s",ObjectName_BodyDlg,Css4BodyContext);
    QWidget *parent=this->parentWidget();
    QWidget* bodyWidget = new QWidget(parent);
    bodyWidget->setObjectName(ObjectName_BodyDlg);




    QVBoxLayout*   verLayoutBody = new QVBoxLayout(bodyWidget);
    verLayoutBody->setSpacing(0);
    verLayoutBody->setContentsMargins(0, 0, 0, 0);
    verLayoutBody->setAlignment(Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop);

    //padTop
    verLayoutBody->addSpacerItem(new QSpacerItem(Width_ProtactorToolView,Pad_Body_TopBottom, QSizePolicy::Fixed));

    QPalette palMapCtrl;
    palMapCtrl.setColor(QPalette::ColorRole::Window, Qt::GlobalColor::white);
    bodyWidget->setPalette(palMapCtrl);

    // QSizePolicy sizePolicy4(QSizePolicy::Policy::Fixed, QSizePolicy::Policy::Fixed);
    // sizePolicy4.setHorizontalStretch(0);
    // sizePolicy4.setVerticalStretch(0);
    // sizePolicy4.setHeightForWidth(bodyWidget->sizePolicy().hasHeightForWidth());
    // bodyWidget->setSizePolicy(sizePolicy4);

    bodyWidget->setStyleSheet(css4Body);

    this->addWidget(bodyWidget);

/*
    QString cssInput;
    QFile file(":/resources/ui/css/LineEdit.txt");
    bool ok = file.open(QIODevice::ReadOnly | QIODevice::Text);
    if(ok)
    {
        //带BOM的存储文件,原始byte[] 是3个字节(ef,bb,bf),只有转换成
        // Qt 使用这种方式，能自动跳过 0xfeff
        QTextStream stream(&file);
        stream.setEncoding(QStringConverter::Utf8);
        cssInput =  stream.readAll();
    }
*/

    QWidget* gpsWidget = new QWidget(bodyWidget);
    QHBoxLayout*   horLayoutAngle = new QHBoxLayout(gpsWidget);
    horLayoutAngle->setSpacing(0);
    horLayoutAngle->setContentsMargins(0, 0, 0, 0);
    horLayoutAngle->setAlignment(Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop);
    horLayoutAngle->addSpacerItem(new QSpacerItem(LeftSpacer_ProtactorTool,Height_TableItem, QSizePolicy::Fixed));

    QSizePolicy sizePoFixed(QSizePolicy::Policy::Fixed, QSizePolicy::Policy::Fixed);
    sizePoFixed.setHorizontalStretch(0);
    sizePoFixed.setVerticalStretch(0);
    sizePoFixed.setHeightForWidth(false);
    gpsWidget->setSizePolicy(sizePoFixed);
    gpsWidget->setFixedSize(Width_ProtactorToolView,Height_TableItem);

    QString textAngle("GPS坐标");
    QLabel *labTitle = new QLabel(textAngle,gpsWidget);
    labTitle->setSizePolicy(sizePoFixed);
    labTitle-> setFixedSize(Width_Label_GpsInput,Height_TableItem);
    labTitle->setAlignment(Qt::AlignmentFlag::AlignRight| Qt::AlignmentFlag::AlignVCenter);
    labTitle->setMargin(0);

    labTitle->setFont(fontLabel);
    // labTitle->setStyleSheet("background:red;");
    horLayoutAngle->addWidget(labTitle);

    horLayoutAngle->addSpacerItem(new QSpacerItem(LeftSpacer_ProtactorTool,Height_TableItem, QSizePolicy::Fixed));

    QLineEdit *lineEdit1 = new QLineEdit(gpsWidget);
    lineEdit1->setEchoMode(QLineEdit::Normal);
    // lineEdit1->setPlaceholderText("Normal");
    lineEdit1->setSizePolicy(sizePoFixed);
    lineEdit1->setFixedSize(Width_GPSInput,Height_input_Default);

    lineEdit1->setStyleSheet(cssInput);

    //lineEdit本身自带returnPressed()信号
    connect(lineEdit1, SIGNAL(returnPressed()), this, SLOT(onGPSWrite()));

    horLayoutAngle->addWidget(lineEdit1);

    horLayoutAngle->addSpacerItem(new QSpacerItem(LeftSpacer_ProtactorTool_R2,Height_TableItem, QSizePolicy::Fixed));


    verLayoutBody->addWidget(gpsWidget);

    //padTop
    // verLayoutBody->addSpacerItem(new QSpacerItem(Width_ProtactorToolView,Pad_Body_TopBottom, QSizePolicy::Fixed));


    QWidget* gpsBtnsWidget = new QWidget(bodyWidget);
    QHBoxLayout*   horLayoutBtns = new QHBoxLayout(gpsBtnsWidget);
    horLayoutBtns->setSpacing(0);
    horLayoutBtns->setContentsMargins(0, 0, 0, 0);
    horLayoutBtns->setAlignment(Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop);
    horLayoutBtns->addSpacerItem(new QSpacerItem(Width_Label_GpsInput,Height_TableItem, QSizePolicy::Fixed));



    GPSValueButtons *gpsBtns = new GPSValueButtons(gpsBtnsWidget,this);
    //本控件继承自QVBoxLayout
    horLayoutBtns->addWidget(gpsBtns);

    verLayoutBody->addWidget(gpsBtnsWidget);

    //padBottom
    verLayoutBody->addSpacerItem(new QSpacerItem(Width_ProtactorToolView,Pad_Body_TopBottom, QSizePolicy::Fixed));

    m_gpsInput = lineEdit1;
    m_BodyWidget = bodyWidget;


    onPickVertexHandler();

    pickVertexToolImpl();
    // mapSurface->repaint();
}

void ProtactorToolView::goView4Segment()
{
    clearViewVertex();
     QWidget *parent = this->parentWidget();
     QString cssInput = QCSS_Input();

    QString css4Body = QString::asprintf("#%s%s",ObjectName_BodyDlg,Css4BodyContext);
    QWidget* bodyWidget = new QWidget(parent);
    bodyWidget->setObjectName(ObjectName_BodyDlg);

    QVBoxLayout*   verLayoutBody = new QVBoxLayout(bodyWidget);
    verLayoutBody->setSpacing(0);
    verLayoutBody->setContentsMargins(0, 0, 0, 0);
    verLayoutBody->setAlignment(Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop);

    //padTop
    verLayoutBody->addSpacerItem(new QSpacerItem(Width_ProtactorToolView,Pad_Body_TopBottom, QSizePolicy::Fixed));

    QPalette palMapCtrl;
    palMapCtrl.setColor(QPalette::ColorRole::Window, Qt::GlobalColor::white);
    bodyWidget->setPalette(palMapCtrl);

    // QSizePolicy sizePolicy4(QSizePolicy::Policy::Fixed, QSizePolicy::Policy::Fixed);
    // sizePolicy4.setHorizontalStretch(0);
    // sizePolicy4.setVerticalStretch(0);
    // sizePolicy4.setHeightForWidth(bodyWidget->sizePolicy().hasHeightForWidth());
    // bodyWidget->setSizePolicy(sizePolicy4);

    bodyWidget->setStyleSheet(css4Body);

    this->addWidget(bodyWidget);

    // QString cssInput = R"()";




    QWidget* angleWidget = new QWidget(bodyWidget);
    QHBoxLayout*   horLayoutAngle = new QHBoxLayout(angleWidget);
    horLayoutAngle->setSpacing(0);
    horLayoutAngle->setContentsMargins(0, 0, 0, 0);
    horLayoutAngle->setAlignment(Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop);
    horLayoutAngle->addSpacerItem(new QSpacerItem(LeftSpacer_ProtactorTool,Height_TableItem, QSizePolicy::Fixed));

    QSizePolicy sizePoFixed(QSizePolicy::Policy::Fixed, QSizePolicy::Policy::Fixed);
    sizePoFixed.setHorizontalStretch(0);
    sizePoFixed.setVerticalStretch(0);
    sizePoFixed.setHeightForWidth(false);
    angleWidget->setSizePolicy(sizePoFixed);
    angleWidget->setFixedSize(Width_ProtactorToolView,Height_TableItem);

    QString textAngle("角度");
    QLabel *labTitle = new QLabel(textAngle,angleWidget);
    labTitle->setSizePolicy(sizePoFixed);
    labTitle-> setFixedSize(Width_ProtactorToolLabel,Height_TableItem);
    labTitle->setAlignment(Qt::AlignmentFlag::AlignRight| Qt::AlignmentFlag::AlignVCenter);
    labTitle->setMargin(0);

    labTitle->setFont(fontLabel);
    // labTitle->setStyleSheet("background:red;");
    horLayoutAngle->addWidget(labTitle);

    horLayoutAngle->addSpacerItem(new QSpacerItem(LeftSpacer_ProtactorTool,Height_TableItem, QSizePolicy::Fixed));

    QLineEdit *lineEdit1 = new QLineEdit(angleWidget);
    lineEdit1->setEchoMode(QLineEdit::Normal);
    // lineEdit1->setPlaceholderText("Normal");
    lineEdit1->setSizePolicy(sizePoFixed);
    lineEdit1->setFixedSize(Width_ProtactorToolInput,Height_input_Default);

        lineEdit1->setStyleSheet(cssInput);
    //lineEdit本身自带returnPressed()信号
    connect(lineEdit1, SIGNAL(returnPressed()), this, SLOT(onProtractorWrite()));

    horLayoutAngle->addWidget(lineEdit1);



    // lineEdit1->setValidator(new QDoubleValidator(-180.0,180.0,2,angleWidget));
    // 0.02-100.0  大于0的浮点数
    QDoubleValidator *doubleValidator = new QDoubleValidator(angleWidget);
    doubleValidator->setRange(-360.00, 360.00, 2);
    lineEdit1->setValidator(doubleValidator);

    lineEdit1->setMaxLength(8);

    horLayoutAngle->addSpacerItem(new QSpacerItem(RightSpacer_Input,Height_TableItem, QSizePolicy::Fixed));

    int IdArray_Angle[] = {AngleMode_Hor,AngleMode_Intersection};
    int IdArray_Seg[] = {AnchorPartSegment_Pre,AnchorPartSegment_Post};

    AngleGridItem * angBtns = new AngleGridItem(angleWidget,this,IdArray_Angle);
    horLayoutAngle->addWidget(angBtns);

    QPalette pal(angleWidget->palette());

    pal.setColor(QPalette::ColorGroup::Active, QPalette::ColorRole::WindowText, QColor(LabelText_Color));
    pal.setColor(QPalette::ColorGroup::Inactive, QPalette::ColorRole::WindowText, QColor(InLabelText_Color));
    pal.setColor(QPalette::ColorGroup::Active, QPalette::ColorRole::ButtonText, QColor(ButtonText_Color));
    pal.setColor(QPalette::ColorGroup::Inactive, QPalette::ColorRole::ButtonText, QColor(InButtonText_Color));
    pal.setColor(QPalette::ColorGroup::Active, QPalette::ColorRole::Window, QColor(Window_Head_Background));
    pal.setColor(QPalette::ColorGroup::Inactive, QPalette::ColorRole::Window, QColor(InWindow_Head_Background));

    angleWidget->setPalette(pal);

    verLayoutBody->addWidget(angleWidget);





    QWidget* segWidget = new QWidget(bodyWidget);

    QHBoxLayout*   horLayoutSeg = new QHBoxLayout(segWidget);
    horLayoutSeg->setSpacing(0);
    horLayoutSeg->setContentsMargins(0, 0, 0, 0);
    horLayoutSeg->setAlignment(Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop);




    QString textSeg("截距(米)");
    QLabel *labSeg = new QLabel(textSeg,segWidget);
    labSeg->setSizePolicy(sizePoFixed);
    labSeg->setFixedSize(Width_ProtactorToolLabel,Height_TableItem);
    labSeg->setAlignment(Qt::AlignmentFlag::AlignRight| Qt::AlignmentFlag::AlignVCenter);
    labSeg->setMargin(0);

    labSeg->setFont(fontLabel);
    // labSeg->setStyleSheet("background:red;");
    horLayoutSeg->addWidget(labSeg);

    horLayoutSeg->addSpacerItem(new QSpacerItem(LeftSpacer_ProtactorTool,Height_TableItem, QSizePolicy::Fixed));


    QLineEdit *lineEdit2 = new QLineEdit(segWidget);
    lineEdit2->setEchoMode(QLineEdit::Normal);
    // lineEdit1->setPlaceholderText("Normal");
    lineEdit2->setSizePolicy(sizePoFixed);
    lineEdit2->setFixedSize(Width_ProtactorToolInput,Height_input_Default);

        lineEdit2->setStyleSheet(cssInput);

    lineEdit2->setMaxLength(16);
    lineEdit2->setReadOnly(true);

    QRegularExpression rx("^(-?[0]|-?[1-9][0-9]{0,5})(?:\\.\\d{1,4})?$|(^\\t?$)");
    QRegularExpressionValidator *pReg = new QRegularExpressionValidator(rx, segWidget);
    lineEdit2->setValidator(pReg);

    horLayoutSeg->addWidget(lineEdit2);


    horLayoutSeg->addSpacerItem(new QSpacerItem(RightSpacer_Input,Height_TableItem, QSizePolicy::Fixed));

    AngleGridItem * segBtns = new AngleGridItem(segWidget,this,IdArray_Seg);
    horLayoutSeg->addWidget(segBtns);


    segWidget->setPalette(pal);
    // segWidget->setStyleSheet(BackgroundCss);
    verLayoutBody->addWidget(segWidget);






    QWidget* segWidgetR2 = new QWidget(bodyWidget);
    QHBoxLayout*   horLayoutSegR2 = new QHBoxLayout(segWidgetR2);
    horLayoutSegR2->setSpacing(0);
    horLayoutSegR2->setContentsMargins(0, 0, 0, 0);
    horLayoutSegR2->setAlignment(Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop);




    QString textSegR2("单节长度(米)");
    QLabel *labSegR2 = new QLabel(textSegR2,segWidgetR2);
    labSegR2->setSizePolicy(sizePoFixed);
    labSegR2->setFixedSize(Width_ProtactorToolLabel,Height_TableItem);
    labSegR2->setAlignment(Qt::AlignmentFlag::AlignRight| Qt::AlignmentFlag::AlignVCenter);
    labSegR2->setMargin(0);

    labSegR2->setFont(fontLabel);
    // labSegR2->setStyleSheet("background:red;");
    horLayoutSegR2->addWidget(labSegR2);

    horLayoutSegR2->addSpacerItem(new QSpacerItem(LeftSpacer_ProtactorTool,Height_TableItem, QSizePolicy::Fixed));

    QLineEdit *lineEditR2 = new QLineEdit(segWidgetR2);
    lineEditR2->setEchoMode(QLineEdit::Normal);
    // lineEdit1->setPlaceholderText("Normal");
    lineEditR2->setSizePolicy(sizePoFixed);
    lineEditR2->setFixedSize(Width_ProtactorToolInput,Height_input_Default);

        lineEditR2->setStyleSheet(cssInput);


    QRegularExpression rxt("^(-?[0]|-?[1-9][0-9]{0,5})(?:\\.\\d{1,4})?$|(^\\t?$)");
    QRegularExpressionValidator *pRegt = new QRegularExpressionValidator(rxt, segWidgetR2);
    lineEditR2->setValidator(pRegt);
    lineEditR2->setMaxLength(16);


    //lineEdit本身自带returnPressed()信号
    connect(lineEditR2, SIGNAL(returnPressed()), this, SLOT(onProtractorWrite()));

    horLayoutSegR2->addWidget(lineEditR2);




    segWidgetR2->setPalette(pal);
    // segWidgetR2->setStyleSheet(BackgroundCss);
    verLayoutBody->addWidget(segWidgetR2);

    //padBottom
    verLayoutBody->addSpacerItem(new QSpacerItem(Width_ProtactorToolView,Pad_Body_TopBottom, QSizePolicy::Fixed));



    m_AngleInput = lineEdit1;
    m_SegInput = lineEdit2;
    m_SegR2Input = lineEditR2;

    m_BodyWidget = bodyWidget;


    pickSegmentToolImpl();
}

void ProtactorToolView::clearViewVertex()
{
    segmentPicked->clear();
    if(mapSurface){
        mapSurface->setActivateTool(NULL);
    }

    if(m_gpsInput)
    {
        m_gpsInput->disconnect(SIGNAL(returnPressed()), this, SLOT(onGPSWrite()));
        m_gpsInput = NULL;
    }

    if(m_AngleInput){

        m_AngleInput->disconnect(SIGNAL(returnPressed()), this, SLOT(onProtractorWrite()));
        m_SegR2Input->disconnect(SIGNAL(returnPressed()), this, SLOT(onProtractorWrite()));

        m_AngleInput = NULL;
        m_SegInput = NULL;
        m_SegR2Input = NULL;


    }

    if(m_BodyWidget){
        delete m_BodyWidget;
        m_BodyWidget=NULL;
    }


}



void ProtactorToolView::onUpdateGPSByString()
{
    onGPSWrite();
}

void ProtactorToolView::onEditEraseVertex()
{
    EditWidget *eww = mapSurface->getEditWidgetSingleton();
    PickedPartLayer *vL =  eww->getEditPointLayer();
    std::vector<PickedPartResult> &data = vL->mData;
    std::size_t numPoints = data.size();
    if(1 ==  numPoints)
    {
        SnapMathUtils snapMath;
        DeleteVertex rpUtils;
        SnapedResult _result;
        const PickedPartResult &it=data[0];
        _result.resultType = it.vertexOrEdge;
        _result.index = it.indexVertex;
        _result.graphic = eww->getEditGraphicR0();

        if(SnapOption::VERTEX == it.vertexOrEdge)
        {
            snapMath.get_vertex_index_snaped(&_result);
            std::unique_ptr<geos::geom::Geometry> removedGeom = rpUtils.delVertex(_result);
            eww->updateGeometry(std::move(removedGeom));

        }


        vL->clearData();
    }else    if(numPoints>1)
    {
        bool isNullGeom;
        double x0,y0;
        AffineTransform worldToScreen;
        SnapeParameter param;
        SnapedResultTag pickResultTag;
        SnapMathUtils snapMath;
        DeleteVertex rpUtils;
        SnapedResult _result;

        mapSurface->getWorldToScreen(worldToScreen);
        snapMath.setworldToScreen(worldToScreen);

        for(const PickedPartResult &it : data)
        {

            x0 = it.x0;
            y0 = it.y0;
            worldToScreen.transformPoint2D(&x0,&y0);

            memset(&param,0,sizeof(SnapeParameter));
            memset(&pickResultTag,0,sizeof(SnapedResultTag));

            param.xMouse = x0;
            param.yMouse = y0;
            param.snapOption = SnapOption::VERTEX;



            eww->snapeByPoint(param,pickResultTag,SnapDataFrom::OnlyEditing);
            // qDebug()  <<__FILE__ <<",Line:"<<__LINE__ << "resultType:" << pickResultTag.resultType <<" (x,y):"<<x0<<","<<y0;

            if(SnapOption::VERTEX == pickResultTag.resultType)
            {
                _result.clear();
                _result.resultType = SnapOption::VERTEX;
                _result.index = pickResultTag.indexVertex;
                _result.graphic = eww->getEditGraphicR0();

                snapMath.get_vertex_index_snaped(&_result);

                {
                    std::unique_ptr<geos::geom::Geometry> removedGeom = rpUtils.delVertex(_result);
                    isNullGeom = false == (removedGeom && removedGeom.get());
                    eww->updateGeometry(std::move(removedGeom));
                    if(isNullGeom)
                        break;
                }


            }
        }

        vL->clearData();
    }
    onPickVertexHandler();
    mapSurface->repaint();
}

void ProtactorToolView::actEditTool(int id, bool checkView)
{
    // MapObject * mapSurface =mapObj;
    QObject *parentTool = dlgHead;
    if(false == IS_EditTool_Affine(id))
    {
        kepen::core::EditWidget* ew = mapSurface->getEditWidgetSingleton();
        ew->getEditPointLayer()->clearData();
    }

    if(EditTool_Vector == id)
    {
        kepen::core::EditTool *tool = new  kepen::core::EditTool(parentTool);
        tool->activate(mapSurface,kepen::core::SnapOption::Any,checkView);


    }else if(EditTool_Pan == id){
        kepen::core::AffinePan *tool = new  kepen::core::AffinePan(parentTool);
        tool->activate(mapSurface);
    }else if(EditTool_Zoom == id){
        kepen::core::AffineZoomScale *tool = new  kepen::core::AffineZoomScale(parentTool);
        tool->activate(mapSurface);
    }else if(EditTool_Rotate == id){
        kepen::core::AffineRotate *tool = new  kepen::core::AffineRotate(parentTool);
        tool->activate(mapSurface);
    }else if(EditTool_Shear == id){
        kepen::core::AffineShear *tool = new  kepen::core::AffineShear(parentTool);
        tool->activate(mapSurface);
    }else if(EditTool_LineSlide == id){
        kepen::core::LineSlideTool *tool = new  kepen::core::LineSlideTool(parentTool);
        tool->activate(mapSurface,kepen::core::LineSlideTool::SegmentDragDefine::SlideProfiling);
    }else if(EditTool_LineExtrude == id){
        kepen::core::LineSlideTool *tool = new  kepen::core::LineSlideTool(parentTool);
        tool->activate(mapSurface,kepen::core::LineSlideTool::SegmentDragDefine::ByExtrude);
    }else if(Edit_AddVertexOnLine == id){
        kepen::core::VertexAddTool *tool = new  kepen::core::VertexAddTool(parentTool);
        tool->activate(mapSurface);
    }

    mapSurface->repaint();
}



void ProtactorToolView::timeoutClosedThiz()
{
    Q_EMIT onViewTabClosedSignals(this);
}

void ProtactorToolView::onPickProtractorHandler(ProtractorPickTool *)
{

    data2view();



    mapSurface->repaint();
}




void ProtactorToolView::onProtractorWrite()
{
    ProtactorParamEdit paramEdited;
    memset(&paramEdited,0,sizeof(paramEdited));

    isValChanged(paramEdited);

    if(paramEdited.state)
    {

        BaseMapTool * t = mapSurface->getActivateTool();
        if(t && ProtractorPickTool_CLASS_TYPE == t->getClassTypeId())
        {
            AffineTransform worldToScreen;
            mapSurface->getWorldToScreen(worldToScreen);
            ProtractorPickTool *tool = dynamic_cast<kepen::core::ProtractorPickTool*>(t);
            segmentPicked->writeNewData(paramEdited,worldToScreen);

            onPickProtractorHandler(tool);
        }




        // mapSurface->repaint();
    }

}

void ProtactorToolView::onGPSWrite()
{
    double x0,y0;
    bool b = tyrParsePointCoords(x0,y0);
    if(b){
        double x1,y1,meter;
        EditWidget *eww = mapSurface->getEditWidgetSingleton();
        PickedPartLayer *vL =  eww->getEditPointLayer();
        vL->getCoord(x1,y1);

        meter = LngLatUtils::GetDistanceR2(x0,y0,x1,y1);
        if (meter > 1000){
            QMessageBox msgBox;
            QString tt = QString::asprintf("新的经度纬度值 与原来的 距离 有 (%.1f)米(%.6f,%.6f)",meter,x1,y1);
            msgBox.setText(tt);
            msgBox.setInformativeText("确定要写入新地址吗？");
            msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel);
            msgBox.setDefaultButton(QMessageBox::Cancel);
            int ret = msgBox.exec();
            if(QMessageBox::Yes ==ret){
                writeGPSImpl(x0,y0);
            }

        }else{
            writeGPSImpl(x0,y0);
        }

    }
}

void ProtactorToolView::writeGPSImpl(double x, double y)
{
    EditWidget *eww = mapSurface->getEditWidgetSingleton();
    PickedPartLayer *vL =  eww->getEditPointLayer();
    std::vector<PickedPartResult> &data = vL->mData;
    std::size_t numPoints = data.size();
    if(1 ==  numPoints)
    {
        SnapMathUtils snapMath;
        DeleteVertex rpUtils;
        SnapedResult _result;
        const PickedPartResult &it=data[0];
        _result.resultType = SnapOption::VERTEX;
        _result.index = it.indexVertex;
        _result.graphic = eww->getEditGraphicR0();


        {
            MoveVertex moveVertex_t;
            snapMath.get_vertex_index_snaped(&_result);
            std::unique_ptr<geos::geom::Geometry> removedGeom = moveVertex_t.moveVertexTo(_result,x,y);
            eww->updateGeometry(std::move(removedGeom));
            vL->updateCoord(x,y);
        }



    }
    mapSurface->repaint();
}

bool ProtactorToolView::tyrParsePointCoords(double &x, double &y)
{
    bool ret = false;
    QString txt = m_gpsInput->text();
    if(txt.isEmpty()||txt.isNull()){

    }else
    {
        QString str = txt.simplified();

        if(str.isEmpty()||str.isNull()){

        }else
        {

            char ch,sp, f1 = '\0',f2 ='\0';
            qsizetype i,len;
            QByteArray chars = str.toLocal8Bit();
            len = chars.length();
            for (i = 0; i < len; i++)
            {
                ch = chars[i];
                if((ch>='0' && ch <= '9') || '-' == ch||'+' == ch || '.'== ch)
                {

                    continue;
                }
                else
                {
                    if(' '==ch)
                        f1 = ch;
                    else
                        f2 = ch ;

                }
            }


            sp = '\0'== f2 ? f1 :f2;

            if (sp != '\0'){
                QChar sep(sp);
                QStringList sl = str.split(sep);
                if(2 == sl.count())
                {
                    bool ok0,ok1;
                    double d0,d1;
                    QString szX = sl[0];
                    QString szY = sl[1];
                    // qDebug()  <<__FILE__ <<",Line:"<<__LINE__ << "str(x,y):"<<szX << ", " <<szY;
                    if(false == (szX.isEmpty()||szX.isNull())
                        && false == (szY.isEmpty()||szY.isNull())){
                        d0 = szX.toDouble(&ok0);
                        d1 = szY.toDouble(&ok1);
                        if(ok0 && ok1)
                        {
                            x = d0;
                            y = d1;
                            return true;
                        }
                    }
                }
            }

        }
    }

    return ret;
}

void ProtactorToolView::onPickVertexHandler()
{

    PickedPartLayer *vL =  mapSurface->getEditWidgetSingleton()->getEditPointLayer();
    std::vector<PickedPartResult> &data = vL->mData;
    std::size_t numPoints = data.size();
    segmentPicked->mProtaData.numVertexPicked = numPoints;
    if(1== numPoints)
    {
        const PickedPartResult &it = data[0];
        QString txt = QString::asprintf("%.6f,%.6f",it.x0,it.y0);
        m_gpsInput->setText(txt);
        m_gpsInput->setReadOnly(false);

    }else
    {
        m_gpsInput->clear();
        m_gpsInput->setReadOnly(true);
    }
}

}
}
